"""数据服务层 - 提供数据获取、分析和导出功能"""

import json
import requests
import pandas as pd
from typing import Dict, Any, List, Optional, Union
from dateutil import parser
import numpy as np
from loguru import logger


class DataAnalysisService:
    """数据分析服务"""
    
    @staticmethod
    def fetch_data(url: str, headers: Optional[Dict[str, str]] = None,
                  params: Optional[Dict[str, Any]] = None,
                  body: Optional[Dict[str, Any]] = None,
                  method: str = 'GET') -> Dict[str, Any]:
        """获取外部API数据
        
        Args:
            url: API地址
            headers: 请求头
            params: 查询参数
            body: 请求体
            method: HTTP方法
            
        Returns:
            获取的数据
        """
        try:
            logger.info(f"正在获取数据: {url}")
            
            # 准备请求参数
            req_kwargs = {
                'timeout': 30
            }
            
            if headers:
                req_kwargs['headers'] = headers
            
            if params:
                req_kwargs['params'] = params
            
            # 发送请求
            if method.upper() == 'GET':
                response = requests.get(url, **req_kwargs)
            elif method.upper() == 'POST':
                req_kwargs['json'] = body
                response = requests.post(url, **req_kwargs)
            elif method.upper() == 'PUT':
                req_kwargs['json'] = body
                response = requests.put(url, **req_kwargs)
            elif method.upper() == 'DELETE':
                response = requests.delete(url, **req_kwargs)
            else:
                raise ValueError(f"不支持的HTTP方法: {method}")
            
            # 检查响应状态
            response.raise_for_status()
            
            return response.json()
            
        except requests.exceptions.RequestException as e:
            logger.error(f"获取数据失败: {str(e)}")
            raise Exception(f"API请求失败: {str(e)}")
        except json.JSONDecodeError:
            logger.error("响应不是有效的JSON格式")
            raise Exception("API返回的不是有效的JSON格式")
    
    @staticmethod
    def extract_data_from_json_path(data: Dict[str, Any], json_path: str) -> List[Dict[str, Any]]:
        """从JSON数据中提取指定路径的数据
        
        Args:
            data: 原始JSON数据
            json_path: JSON路径（支持点号分隔的嵌套路径，如 'data.items'）
            
        Returns:
            提取的数据列表
        """
        try:
            if not json_path:
                # 如果没有指定路径，尝试返回顶层列表
                if isinstance(data, list):
                    return data
                # 或者返回顶层字典
                elif isinstance(data, dict):
                    return [data]
                raise ValueError("数据不是有效的JSON格式")
            
            # 解析JSON路径
            path_parts = json_path.split('.')
            current_data = data
            
            for part in path_parts:
                if isinstance(current_data, dict) and part in current_data:
                    current_data = current_data[part]
                else:
                    raise ValueError(f"无法找到路径: {json_path}")
            
            # 确保返回的是列表
            if isinstance(current_data, list):
                return current_data
            elif isinstance(current_data, dict):
                return [current_data]
            else:
                raise ValueError(f"路径指向的数据不是列表或字典: {type(current_data)}")
                
        except Exception as e:
            logger.error(f"提取数据失败: {str(e)}")
            raise Exception(f"提取数据失败: {str(e)}")
    
    @staticmethod
    def create_dataframe(data_list: List[Dict[str, Any]]) -> pd.DataFrame:
        """将数据列表转换为DataFrame
        
        Args:
            data_list: 数据列表
            
        Returns:
            转换后的DataFrame
        """
        try:
            df = pd.DataFrame(data_list)
            logger.info(f"创建DataFrame成功，包含 {len(df)} 行数据")
            return df
        except Exception as e:
            logger.error(f"创建DataFrame失败: {str(e)}")
            raise Exception(f"创建DataFrame失败: {str(e)}")
    
    @staticmethod
    def parse_dates(df: pd.DataFrame, date_field: Optional[str] = None) -> pd.DataFrame:
        """解析日期字段
        
        Args:
            df: 原始DataFrame
            date_field: 日期字段名
            
        Returns:
            处理后的DataFrame
        """
        if date_field and date_field in df.columns:
            try:
                # 尝试解析日期
                df[date_field] = pd.to_datetime(df[date_field], errors='coerce')
                # 移除无效的日期行
                df = df.dropna(subset=[date_field])
                logger.info(f"成功解析日期字段: {date_field}")
            except Exception as e:
                logger.warning(f"解析日期字段失败: {str(e)}")
        return df
    
    @staticmethod
    def analyze_data(df: pd.DataFrame, group_by: Optional[str] = None,
                    date_field: Optional[str] = None, freq: Optional[str] = None,
                    value_field: Optional[str] = None, agg: str = 'count') -> Dict[str, Any]:
        """分析数据
        
        Args:
            df: 输入的DataFrame
            group_by: 分组字段
            date_field: 日期字段
            freq: 日期聚合频率（day, week, month等）
            value_field: 值字段
            agg: 聚合方法（count, sum, mean, max, min）
            
        Returns:
            分析结果
        """
        try:
            result = {
                'original_count': len(df),
                'columns': list(df.columns),
                'sample_data': df.head(5).to_dict('records'),
                'basic_stats': {},
                'aggregation': None
            }
            
            # 基本统计信息
            for col in df.columns:
                col_data = df[col]
                col_stats = {}
                
                # 检查数据类型
                if pd.api.types.is_numeric_dtype(col_data):
                    col_stats.update({
                        'count': int(col_data.count()),
                        'mean': float(col_data.mean()),
                        'median': float(col_data.median()),
                        'std': float(col_data.std()),
                        'min': float(col_data.min()),
                        'max': float(col_data.max())
                    })
                else:
                    # 对于非数值列，统计唯一值数量等
                    col_stats.update({
                        'count': int(col_data.count()),
                        'unique_count': int(col_data.nunique()),
                        'top_value': str(col_data.mode().iloc[0]) if not col_data.mode().empty else None
                    })
                
                result['basic_stats'][col] = col_stats
            
            # 执行聚合分析
            if group_by or (date_field and freq):
                agg_df = df.copy()
                group_cols = []
                
                # 处理日期聚合
                if date_field and date_field in agg_df.columns and freq:
                    try:
                        # 确保日期字段已解析
                        if not pd.api.types.is_datetime64_any_dtype(agg_df[date_field]):
                            agg_df[date_field] = pd.to_datetime(agg_df[date_field], errors='coerce')
                            agg_df = agg_df.dropna(subset=[date_field])
                        
                        # 按频率重采样
                        agg_date_col = f"{date_field}_aggregated"
                        agg_df[agg_date_col] = agg_df[date_field].dt.to_period(freq).dt.to_timestamp()
                        group_cols.append(agg_date_col)
                    except Exception as e:
                        logger.warning(f"日期聚合失败: {str(e)}")
                
                # 添加分组字段
                if group_by and group_by in agg_df.columns:
                    group_cols.append(group_by)
                
                # 执行聚合
                if group_cols:
                    # 确定要聚合的字段
                    agg_fields = {}
                    if value_field and value_field in agg_df.columns and pd.api.types.is_numeric_dtype(agg_df[value_field]):
                        agg_fields[value_field] = agg
                    else:
                        # 如果没有指定值字段或值字段不是数值类型，则聚合计数
                        agg_fields['count'] = 'count'
                    
                    # 执行分组聚合
                    grouped = agg_df.groupby(group_cols).agg(agg_fields).reset_index()
                    
                    # 格式化结果
                    result['aggregation'] = {
                        'group_by': group_cols,
                        'aggregation': agg_fields,
                        'data': grouped.to_dict('records')
                    }
            
            logger.info("数据分析完成")
            return result
            
        except Exception as e:
            logger.error(f"数据分析失败: {str(e)}")
            raise Exception(f"数据分析失败: {str(e)}")
    
    @staticmethod
    def export_to_excel(df: pd.DataFrame) -> bytes:
        """将数据导出为Excel
        
        Args:
            df: 输入的DataFrame
            
        Returns:
            Excel文件的字节数据
        """
        try:
            # 创建Excel写入器
            from io import BytesIO
            output = BytesIO()
            
            with pd.ExcelWriter(output, engine='openpyxl') as writer:
                # 写入主数据
                df.to_excel(writer, index=False, sheet_name='数据')
                
                # 添加统计信息
                stats_sheet = writer.book.create_sheet('统计信息')
                stats_sheet.append(['字段名', '类型', '非空计数', '唯一值', '均值', '最小值', '最大值'])
                
                for col in df.columns:
                    col_data = df[col]
                    col_type = str(col_data.dtype)
                    non_null_count = int(col_data.count())
                    unique_count = int(col_data.nunique())
                    
                    # 数值列的统计
                    mean_val = '-' if not pd.api.types.is_numeric_dtype(col_data) else f"{float(col_data.mean()):.2f}"
                    min_val = '-' if not pd.api.types.is_numeric_dtype(col_data) else f"{float(col_data.min()):.2f}"
                    max_val = '-' if not pd.api.types.is_numeric_dtype(col_data) else f"{float(col_data.max()):.2f}"
                    
                    stats_sheet.append([col, col_type, non_null_count, unique_count, mean_val, min_val, max_val])
            
            output.seek(0)
            logger.info(f"Excel导出完成，共 {len(df)} 行数据")
            return output.getvalue()
            
        except Exception as e:
            logger.error(f"Excel导出失败: {str(e)}")
            raise Exception(f"Excel导出失败: {str(e)}")


# 全局服务实例
data_analysis_service = DataAnalysisService()